-- 2022-8-8

---[[ 无符号整数

    -- 整型表示中使用一个比特来存储符号位
    -- 因此 64位整型数最大可以表示2^63-1而不是2^64-1 这点区别是无关紧要的 因为2^63-1已经相当大了
    -- 不过 由于我们需要处理使用无符号整型表示的外部数据或实现一些需要64位整型数的算法 因而有时候也不能浪费这个符号位
    -- 此外 在精简Lua中 这种区别可能会很重要
    -- 例如 如果用一个32位有符号整型数表示整型数表示文件中的位置 那么能够操作的最大文件大小为2GB 而无符号能操作4GB

    -- Lua语言不显示支持无符号整数 不过尽管如此 主要稍加注意 在Lua中处理无符号整数并不难
    -- 虽然看上去不友好 但是可以直接写出比2^63大的常量
    local x = 13835058055282163712
    print(x)
    print(2^63-1)

    -- Lua语言输出常量的方式 默认情况下 打印数值时 是将其作为有符号整型数进行处理的 我们可以使用选项%u或%x四级成绩无符号整型数
    -- 根据有符号整型数的表示方法(2的补码) 加减乘法操作对于有符号整型数和无符号整型数是一样的

    -- 关系运算对于有符号整数和无符号整数是不一样的 当比较具有不同符号的整型数就会出现问题
    -- 对于有符号整型数而言 符号位被置位(位运算中的置位 设置为1)的整数更小 因为它代表的是负数
    -- 补充 在存储时例如4位存储 0000-1111 从中间分开 左边表示0和正 右边表示负

    -- 如果把两个整型数都当作无符号的 那么结果显然是不正确的 因此 我们需要使用不同的操作来比较无符号整型数
    -- Lua5.3提供了函数math.ult(unsigned less than)来完成这个需求
    print(math.ult(1,2))

    -- 另一种方法是在进行有符号比较前先用掩码(使用运算符来实现)掩去两个操作数的符号位
    
    -- 无符号除法也不一样
    ---[[ 13.1
        function udiv(n,d)
            if d < 0 then
                if math.ult(n,d) then
                    return 0
                end
                else
                    return 1
            end
            local q = ((n>>1)//d)<<1
            local r = n - q * d
            if not math.ult(r,d) then
                q = q + 1
            end
            return q
        end
    --]]
    -- 第一个比较(d<0)等价于比较d是否大于2^63 如果大于 那么商只能是1(如果n大于或大于d)或0
    -- 否则 我们把被除数除以2 然后除以除数 然后把结果乘以2
    -- 右移1位等价于除以2的无符号除法，其结果是一个非负有符号整数 后续的左移纠正了商 还原了之前的除法

    -- 总体上说 floor(floor(n/2)/d)*2(算法进行的计算)与floor(((n/2)/d)*2)(正确的结果)并不等价
    -- 不过 要证明它们之间最多相差1并不困难 因此 算符计算了余数(变量r) 然后判断余数是否比除数大 如果余数比除数大则纠正商(加1)即可

    -- 无符号整型数和浮点整型数之间的转换需要一些调整 要把一个无符号整数转换为浮点型数 可以先将其转换成有符号整型数 然后通过取模运算纠正结果
    do
        local u = 11529215046068469760
        local f = (u + 0.0) % 2^64
        print(string.format("%.0f",f))
    end



    
    -- 此处省略…… 
    -- 看不明白 打个标记
--]]